-----------------------------------------------------------------------------
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
-- 
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--! @file
--! @brief First communication test with the camera testbench
--! @author BLANCHARD Remy <remyb718 at gmail dot com>
--!
--! Platform   : Spartan 3
--!
--! Description: This file is the test bench for the bloc that store the 12 
--!              first lines of the camera (OV7620) and stop until a reset of
--!              the iMX
-----------------------------------------------------------------------------


LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY t_cam2imx IS
END t_cam2imx;

ARCHITECTURE behavior_1 OF t_cam2imx IS 
  -- Component Declaration
  COMPONENT cam2imx
  PORT(
    clk_i          : in  std_logic;
    rst_i          : in  std_logic;
    
    -- camera side
    -- Y signal (see documentation)
    Y_i            : in  std_logic_vector(7 downto 0);
    -- UV signal (see documentation)
    UV_i           : in  std_logic_vector(7 downto 0);
    PCLK_i         : in  std_logic;
    HREF_i         : in  std_logic;
    VSYNC_i        : in  std_logic;
    FODD_i         : in  std_logic;

    -- iMX side
    DataxD_io      : inout std_logic_vector(15 downto 0);
    AddrxDI_i      : in std_logic_vector(12 downto 0);
    CSxBI_i        : in std_logic;
    WRxBI_i        : in std_logic;
    RDxBI_i        : in std_logic);
  END COMPONENT;

  SIGNAL clk_s          : std_logic;
  SIGNAL rst_s          : std_logic;
  SIGNAL Y_s            : std_logic_vector(7 downto 0);
  SIGNAL UV_s           : std_logic_vector(7 downto 0);
  SIGNAL PCLK_s         : std_logic;
  SIGNAL HREF_s         : std_logic;
  SIGNAL VSYNC_s        : std_logic;
  SIGNAL FODD_s         : std_logic;

  SIGNAL DataxD_s       : std_logic_vector(15 downto 0);
  SIGNAL AddrxDI_s      : std_logic_vector(12 downto 0);
  SIGNAL CSxBI_s        : std_logic;
  SIGNAL WRxBI_s        : std_logic;
  SIGNAL RDxBI_s        : std_logic;

  -- timing constant
  constant periode_c : time := 10 ns;     -- 100 MHz
  constant periode_cc: time := 100 ns;    -- 10 MHz

BEGIN

-- Component Instantiation
  uut: cam2imx PORT MAP(
    clk_i        => clk_s,
    rst_i        => rst_s,
 
    Y_i          => Y_s,
    UV_i         => UV_s,
    PCLK_i       => PCLK_s,
    HREF_i       => HREF_s,
    VSYNC_i      => VSYNC_s,
    FODD_i       => FODD_s,

    DataxD_io    => DataxD_s,
    AddrxDI_i    => AddrxDI_s,
    CSxBI_i      => CSxBI_s,
    WRxBI_i      => WRxBI_s,
    RDxBI_i      => RDxBI_s
  );

  -- input: clock
  clock_p : PROCESS
  BEGIN
    clk_s <= '1', '0' after periode_c/2;
    wait for periode_c;
  end process clock_p;

  -- input: camera reset
  camera_rst_p : PROCESS
  BEGIN
    VSYNC_s <= '1', '0' after periode_cc*8;
    wait for 42*periode_cc;
  end process camera_rst_p;

  -- input: general reset
  reset_p : PROCESS
  BEGIN
    rst_s <= '1', '0' after periode_c*2;
    wait for 100*periode_cc;
  end process reset_p;

  -- input: camera clock
  cam_clock_p : PROCESS
  BEGIN
    PCLK_s <= '0', '1' after periode_cc/2;
    wait for periode_cc;
  end process cam_clock_p;

  -- input: FODD
  new_line_p : PROCESS
  BEGIN
    FODD_s <= '1', '0' after periode_cc*6;
    wait for periode_cc*12;
  end process new_line_p;

  -- input: HREF
  new_image_p : PROCESS
  BEGIN
    HREF_s <= '1', '0' after periode_cc*64;
    wait for periode_cc*72;
  end process new_image_p;
  
  -- input: Y
  Y_p : PROCESS
  BEGIN
    Y_s <= "10101010";
    wait for periode_cc;
    Y_s <= "01010101";
    wait for periode_cc;
    Y_s <= "11111111";
    wait for periode_cc;
    Y_s <= "00000000";
    wait for periode_cc;
    Y_s <= "11110000";
    wait for periode_cc;
    Y_s <= "10101010";
    wait for periode_cc;
  end process Y_p;

  -- input: UV
  UV_p : PROCESS
  BEGIN
    UV_s <= "00001111";
    wait for periode_cc;
    UV_s <= "11001100";
    wait for periode_cc;
    UV_s <= "00110011";
    wait for periode_cc;
    UV_s <= "11111111";
    wait for periode_cc;
    UV_s <= "10101010";
    wait for periode_cc;
    UV_s <= "00000000";
    wait for periode_cc;
  end process UV_p;


  -- input: read RAM
  read_RAM_p : PROCESS
  BEGIN
    CSxBI_s<='1';
    RDxBI_s<='1';
    WRxBI_s<='1';
    DataxD_s <= (others  => 'Z');
    AddrxDI_s<=(others  => 'Z');
    wait for 50*periode_cc;
	 
    -- setting the reading mode
    CSxBI_s<='0';
    RDxBI_s<='1';
    WRxBI_s<='0';
    DataxD_s <="0000000000000000";
    AddrxDI_s<="0000000000010";
    wait for 2*periode_c;
    -- read the datas
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000000";
    wait for 2*periode_c;
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000001";
    wait for 2*periode_c;
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000010";
    wait for 2*periode_c;
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000011";
    wait for 2*periode_c;

    -- setting the reading mode
    CSxBI_s<='0';
    RDxBI_s<='1';
    WRxBI_s<='0';
    DataxD_s <="0000000000000001";
    AddrxDI_s<="0000000000010";
    wait for 2*periode_c;
	 -- read the Fodd
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000000";
    wait for 2*periode_c;
    CSxBI_s<='0';
    RDxBI_s<='0';
    WRxBI_s<='1';
    DataxD_s <=(others  => 'Z');
    AddrxDI_s<="0000000000001";
    wait for 2*periode_c;

    -- test iMX reset of the state machine
    CSxBI_s<='0';
    RDxBI_s<='1';
    WRxBI_s<='0';
    DataxD_s <= (others  => 'Z');
    AddrxDI_s<="0000000000001";
    wait for 2*periode_c;
  end process read_RAM_p;

END;
